/*
 * Copyright (c) 2018 Hitevision
 */

package tw.com.hitevision.whiteboard.android.screenshot;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import android.widget.ImageView;

import tw.com.hitevision.whiteboard.android.R;

import static android.content.Context.WINDOW_SERVICE;

/**
 * This class animates screenshots.
 */
public class ScreenshotHelper {
    private static final String TAG = ScreenshotHelper.class.getSimpleName();

    private static final int DURATION_ANIM_FLASH = 400;
    private static final int DURATION_ANIM_IN = 400;
    private static final int DURATION_ANIM_OUT = 400;

    private static final float ALPHA_SCREENSHOT = 0.8f;

    private final WindowManager windowManager;
    private final WindowManager.LayoutParams layoutParams;

    private final View root;
    private final View flash;
    private final ImageView screenshot;
    private final Point point;
    private final AnimatorSet set;

    public ScreenshotHelper(Context context) {
        root = LayoutInflater.from(context).inflate(R.layout.window_screenshot, null);
        screenshot = root.findViewById(R.id.screenshot);
        flash = root.findViewById(R.id.flash);

        windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE);

        layoutParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);

        point = new Point();
        set = new AnimatorSet();
    }

    public void cancel() {
        if (set.isStarted()) {
            set.cancel();
        }
    }

    public void animate(Bitmap bitmap, OnAnimationEndListener listener) {
        log("animate: listener=" + (listener != null));
        screenshot.setImageBitmap(bitmap);

        try {
            windowManager.addView(root, layoutParams);
        } catch (IllegalStateException e) {
            e.printStackTrace();

            try {
                windowManager.removeViewImmediate(root);
            } catch (IllegalArgumentException iae) {
                iae.printStackTrace();
            }

            if (listener != null) {
                listener.onAnimationEnd();
            }
            return;
        }

        if (set.isStarted()) {
            log("- cancelling started set!");
            set.cancel();
        }

        set.play(createInAnim(screenshot))
                .with(createFlashAnim(flash))
                .before(createOutAnim(screenshot));
        set.removeAllListeners();
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                screenshot.setTranslationX(0);
                screenshot.setAlpha(ALPHA_SCREENSHOT);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                log("onAnimationEnd");
                try {
                    windowManager.removeViewImmediate(root);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                }
                if (listener != null) {
                    listener.onAnimationEnd();
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                try {
                    windowManager.removeViewImmediate(root);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                }
            }
        });
        set.start();
    }

    public void end() {
        set.end();
    }

    private Animator createFlashAnim(View target) {
        windowManager.getDefaultDisplay().getSize(point);
        ObjectAnimator animation = ObjectAnimator.ofFloat(target, "alpha", 1.0f, 0.0f);
        animation.setDuration(DURATION_ANIM_FLASH);
        return animation;
    }

    private Animator createInAnim(View target) {
        final AnimatorSet set = new AnimatorSet();

        ObjectAnimator animX = ObjectAnimator.ofFloat(target, "scaleX", 1.0f, 0.8f);
        animX.setDuration(DURATION_ANIM_IN);

        ObjectAnimator animY = ObjectAnimator.ofFloat(target, "scaleY", 1.0f, 0.8f);
        animY.setDuration(DURATION_ANIM_IN);

        set.playTogether(animX, animY);
        return set;
    }

    private Animator createOutAnim(View target) {
        windowManager.getDefaultDisplay().getSize(point);
        ObjectAnimator animation = ObjectAnimator.ofFloat(target, "translationX", 0.00f, -point.x);
        animation.setDuration(DURATION_ANIM_OUT);
        animation.setInterpolator(new AccelerateInterpolator());
        return animation;
    }

    public interface OnAnimationEndListener {
        void onAnimationEnd();
    }

    private static void log(String msg) {
        Log.d(TAG, msg);
    }
}
